﻿namespace ScrumLite.WebUx.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using ScrumLite.Services;
    using ScrumLite.Services.Contracts;
    using ScrumLite.WebUx.Controllers;
    using ScrumLite.WebUx.Models;
    using System.Configuration;
    using System.Globalization;
    using System.Security.Permissions;
    using System.Web.Mvc;

    /// <summary>
    /// Summary description for RequestsControllerFixture
    /// </summary>
    [TestClass]
    public class RequestsControllerFixture
    {
        [TestMethod]
        public void ShouldShowOpenedBacklog()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.Read(Guid.NewGuid().ToString(), "Opened", null);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsReadViewData));
        }

        [TestMethod]
        public void ShouldReadOne()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.ReadOne(Guid.NewGuid().ToString(), 1, 0);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsWriteViewData));
        }

        [TestMethod]
        public void ShouldShowCommittedBacklog()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.Read(Guid.NewGuid().ToString(), "Iteration", null);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsReadViewData));
        }

        [TestMethod]
        public void ShouldShowAllBacklog()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.Read(Guid.NewGuid().ToString(), "All", null);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsReadViewData));
        }

        [TestMethod]
        public void ShouldShowAllBacklogToAWorkArea()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            string workAreaName = "newArea";

            controller.Read(Guid.NewGuid().ToString(), "All", workAreaName);

            Assert.IsNotNull(controller.DataToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsReadViewData));
        }
        
        [TestMethod]
        public void ShouldRenderReadAllViewWhenModeIsClose()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, string.Empty, "Tester", "Test Title", 2, 3, "Test notes", 1, false, "close", null);

            Assert.IsTrue(service.AddRequestCalled);
            Assert.IsTrue(controller.DataRedirectToAction.ToString().Contains("Action = Read"));
            Assert.IsTrue(controller.DataRedirectToAction.ToString().Contains("Mode = All"));
        }

        [TestMethod]
        public void ShouldRenderWriteViewAndDataIsEmptyWhenModeIsNew()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, string.Empty, "Tester", "Test Title", 2, 3, "Test notes", 1, false, "new", null);

            Assert.IsTrue(service.AddRequestCalled);
            Assert.AreEqual("Write", controller.ViewToShow);
            Assert.IsNull(((RequestsWriteViewData)controller.DataToShow).Request);
        }

        [TestMethod]
        public void ShouldRenderWriteViewAndDataIsNotEmptyWhenModeIsUpdate()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, "5CFD07A8-FBA8-4248-BA20-4CBF9E969FCC", "Tester", "Test Title", 2, 3, "Test notes", 1, false, "update", null);

            Assert.IsTrue(service.UpdateRequestCalled);
            Assert.AreEqual("Write", controller.ViewToShow);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).Request);
        }

        [TestMethod]
        public void ShouldAddRequestWhenRequestIdIsNotSpecified()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, string.Empty, "Tester", "Test Title", 2, 3, "Test notes", 1, false, "close", null);

            Assert.IsTrue(service.AddRequestCalled);
        }

        [TestMethod]
        public void ShouldAddRequestWithDueOn()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            DateTime dueOn = DateTime.Today.Add(new TimeSpan(100,0,0,0));

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, string.Empty, "Tester", "Test Title", 2, 3, "Test notes", 1, false, "close", dueOn);

            Assert.IsTrue(service.AddRequestCalled);
            Assert.IsNotNull(service.ProcessedRequest);
            Assert.AreEqual(dueOn, service.ProcessedRequest.DueOn);

            TimeSpan ts1 = new TimeSpan(99, 0, 0, 0);
            TimeSpan ts2 = new TimeSpan(101, 0, 0, 0);

            Assert.IsTrue(ts1.CompareTo(service.ProcessedRequest.TimeSpanToDue)<0);
            Assert.IsTrue(ts2.CompareTo(service.ProcessedRequest.TimeSpanToDue)>0);
        }

        [TestMethod]
        public void ShouldUpdateRequestWithDueOn()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            DateTime dueOn = new DateTime(2008, 12, 31);

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, "5CFD07A8-FBA8-4248-BA20-4CBF9E969FCC", "Tester", "Test Title", 2, 3, "Test notes", 1, false, "close", dueOn);

            Assert.IsTrue(service.UpdateRequestCalled);
            Assert.IsNotNull(service.ProcessedRequest);
            Assert.AreEqual(dueOn, service.ProcessedRequest.DueOn);
        }

        [TestMethod]
        public void ShouldUpdateRequestWhenARequestIdIsSpecified()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, "5CFD07A8-FBA8-4248-BA20-4CBF9E969FCC", "Tester", "Test Title", 2, 3, "Test notes", 1, false, "close", null);

            Assert.IsTrue(service.UpdateRequestCalled);
        }

        [TestMethod]
        public void ShouldUpdateRequestWhenARequestIdIsSpecifiedAndPriorityIsNull()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());
            MockHelpers.SetupMocks(controller);

            controller.Request.Form["chkWorkAreas"] = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB";

            controller.Write("AF06A611-12CE-4C06-B3AD-E2754D12D516", 70, "5CFD07A8-FBA8-4248-BA20-4CBF9E969FCC", "Tester", "Test Title", null, 3, "Test notes", 1, false, "close", null);

            Assert.IsTrue(service.UpdateRequestCalled);
        }

        [TestMethod]
        public void ShouldGetStatusList()
        {
            MockRequestsService service = new MockRequestsService();

            Dictionary<string, string> statusList = service.GetStatusList();

            Assert.AreEqual(5, statusList.Count());
        }

        [TestMethod]
        public void ShouldDeleteARequest()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.Delete(Guid.NewGuid().ToString(), Guid.NewGuid().ToString(), 0);

            Assert.IsTrue(service.DeleteRequestCalled);
        }

        [TestMethod]
        public void ShouldShowWorkAreasAssociatedToARequestInReadWorkAreaView()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.ReadWorkArea("AF06A611-12CE-4C06-B3AD-E2754D12D516", 1);

            Assert.IsTrue(service.GetWorkAreasCalled);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(ReadWorkAreaViewData));
        }

        [TestMethod]
        public void ShouldPassToWriteViewWorkAreasAssociatedToARequestInReadOneAction()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.ReadOne("AF06A611-12CE-4C06-B3AD-E2754D12D516", 1, 1);

            Assert.IsTrue(service.GetWorkAreasCalled);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData.WorkAreas);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData.SelectedWorkAreas);
        }

        [TestMethod]
        public void ShouldPassToWriteViewExistingWorkAreasInNewAction()
        {
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service, new MockProfileService());

            controller.New("AF06A611-12CE-4C06-B3AD-E2754D12D516", 1);

            Assert.IsTrue(service.GetWorkAreasCalled);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData);
            Assert.IsNotNull(((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData.WorkAreas);
            Assert.AreEqual(0,((RequestsWriteViewData)controller.DataToShow).WorkAreasPickerViewData.SelectedWorkAreas.Count());
        }

        [TestMethod]
        public void ShouldRenderRequestsMetricsWithData()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService service = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(service);

            controller.RequestsMetrics(mockProjectUri);

            Assert.AreEqual("RequestsMetrics", controller.ViewToShow);
            Assert.IsInstanceOfType(controller.DataToShow, typeof(RequestsMetricsData));
            Assert.IsInstanceOfType(controller.DataToShow, typeof(ContextViewData));
        }

        [TestMethod]
        public void ShouldCallGetWeeklyWeightOnRenderRequestsMetricsView()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            requestsService.GetWeeklyWeightCalled = false;
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            Assert.IsTrue(requestsService.GetWeeklyWeightCalled);
            Assert.IsNotNull(((RequestsMetricsData)controller.DataToShow).WeeklyWeight);
            Assert.AreEqual(6, ((RequestsMetricsData)controller.DataToShow).WeeklyWeight.Count);
        }

        [TestMethod]
        public void ShouldCallGetRequestsByStatusByWorkAreasOnRenderRequestsMetricsView()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            requestsService.GetRequestsByStatusByWorkAreaCalled = false;
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            Assert.IsTrue(requestsService.GetRequestsByStatusByWorkAreaCalled);
            Assert.IsNotNull(((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas);
            Assert.AreEqual(2, ((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas.Count);
            Assert.IsTrue(((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas.Any(f => f.Key.Name == "Site Admin Tool"));
            Assert.IsTrue(((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas.Any(f => f.Key.Name == "Modularity"));
            Dictionary<RequestStatus, int> siteAdminToolRequests = ((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas.Single(f => f.Key.Name == "Site Admin Tool").Value;
            Dictionary<RequestStatus, int> modularityRequests = ((RequestsMetricsData)controller.DataToShow).RequestsByStatusByWorkAreas.Single(f => f.Key.Name == "Modularity").Value;
            Assert.AreEqual(1, siteAdminToolRequests[RequestStatus.Blocked]);
            Assert.AreEqual(4, siteAdminToolRequests[RequestStatus.Completed]);
            Assert.AreEqual(0, siteAdminToolRequests[RequestStatus.Postponed]);
            Assert.AreEqual(3, siteAdminToolRequests[RequestStatus.Taken]);
            Assert.AreEqual(2, siteAdminToolRequests[RequestStatus.Waiting]);
            Assert.AreEqual(1, modularityRequests[RequestStatus.Blocked]);
            Assert.AreEqual(4, modularityRequests[RequestStatus.Completed]);
            Assert.AreEqual(0, modularityRequests[RequestStatus.Postponed]);
            Assert.AreEqual(3, modularityRequests[RequestStatus.Taken]);
            Assert.AreEqual(2, modularityRequests[RequestStatus.Waiting]);
        }

        [TestMethod]
        public void ShouldCallGetRequestsByStatusOnRenderRequestsMetricsView()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            requestsService.GetRequestsByStatusCalled = false;
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            Assert.IsTrue(requestsService.GetRequestsByStatusCalled);
            Assert.IsNotNull(((RequestsMetricsData)controller.DataToShow).RequestsByStatus);
            Assert.AreEqual(5, ((RequestsMetricsData)controller.DataToShow).RequestsByStatus.Count);
            Dictionary<RequestStatus, int> modularityRequests = ((RequestsMetricsData)controller.DataToShow).RequestsByStatus;
            Assert.AreEqual(2, modularityRequests[RequestStatus.Blocked]);
            Assert.AreEqual(8, modularityRequests[RequestStatus.Completed]);
            Assert.AreEqual(0, modularityRequests[RequestStatus.Postponed]);
            Assert.AreEqual(6, modularityRequests[RequestStatus.Taken]);
            Assert.AreEqual(4, modularityRequests[RequestStatus.Waiting]);
        }

        [TestMethod]
        public void ShouldGenerateRequestsByStatusMetricsPieUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=p3&chs=350x150&chd=t:6.0,4.0,2.0,8.0,0.0&chtt=Requests+by+status&chco=FFFF55,AAAAAA,FF5555,55FF55,5555FF&chl=Taken%20(6)|Waiting%20(4)|Blocked%20(2)|Completed%20(8)|Postponed%20(0)";
            Assert.AreEqual(expectedUrl, ((RequestsMetricsData)controller.DataToShow).GChartRequestsByStatusPie);
        }

        [TestMethod]
        public void ShouldGenerateRequestsMetricsLineUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            string expectedUrl = @"http://chart.apis.google.com/chart?cht=lc&chs=500x250&chd=t:20.0,24.0,50.0,45.0,55.0,93.0|47.8,47.8&chtt=Weekly+weight+completed&chco=55FF55,0000FF&chdl=Weight|Average&chxt=x,y&chxl=0:|W1|W2|W3|W4|W5|W6|1:&chxr=1,0,100&chls=3,1,0|1,6,3";
            Assert.AreEqual(expectedUrl, ((RequestsMetricsData)controller.DataToShow).GChartRequestsLine);
        }

        [TestMethod]
        public void ShouldGenerateEmptyRequestsMetricsLineUrl()
        {
            string mockProjectUri = MockRequestsService.ProjectIdForEmptyData;
            MockRequestsService commitmentService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(commitmentService);

            controller.RequestsMetrics(mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyRequestByStatusPie.png");
            Assert.AreEqual(expectedUrl, ((RequestsMetricsData)controller.DataToShow).GChartRequestsLine);
        }

        [TestMethod]
        public void ShouldGenerateRequestsByStatusByWorkAreasMetricsBarsUrl()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            string expectedUrl1 = @"http://chart.apis.google.com/chart?cht=bvg&chs=400x150&chd=t:30.0|20.0|10.0|40.0|0.0&chtt=Site+Admin+Tool&chco=FFFF55,AAAAAA,FF5555,55FF55,5555FF&chdl=Taken|Waiting|Blocked|Completed|Postponed&chxt=y&chxl=0:&chxr=0,0,10&chbh=20,5,50";
            string expectedUrl2 = @"http://chart.apis.google.com/chart?cht=bvg&chs=400x150&chd=t:30.0|20.0|10.0|40.0|0.0&chtt=Modularity&chco=FFFF55,AAAAAA,FF5555,55FF55,5555FF&chdl=Taken|Waiting|Blocked|Completed|Postponed&chxt=y&chxl=0:&chxr=0,0,10&chbh=20,5,50";
            Assert.AreEqual(2, ((RequestsMetricsData)controller.DataToShow).GChartRequestsByStatusByWorkAreaBars.Count());
            Assert.AreEqual(expectedUrl1, ((RequestsMetricsData)controller.DataToShow).GChartRequestsByStatusByWorkAreaBars[0]);
            Assert.AreEqual(expectedUrl2, ((RequestsMetricsData)controller.DataToShow).GChartRequestsByStatusByWorkAreaBars[1]);
        }

        [TestMethod]
        public void ShouldGenerateEmptyRequestsByStatusByWorkAreasMetricsBarsUrl()
        {
            string mockProjectUri = MockRequestsService.ProjectIdForEmptyData;
            MockRequestsService commitmentService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(commitmentService);

            controller.RequestsMetrics (mockProjectUri);

            string expectedUrl = String.Format(CultureInfo.InvariantCulture,"/{0}/{1}", ConfigurationManager.AppSettings["SiteImagesPath"], "chart_EmptyRequestByStatusPie.png");
            Assert.AreEqual(expectedUrl, ((RequestsMetricsData)controller.DataToShow).GChartRequestsByStatusPie);
        }

        [TestMethod]
        public void ShouldNotFailOnEmptyWeeklyWeight()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            requestsService.WeeklyWeightToReturn.Clear();
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.RequestsMetrics(mockProjectUri);

            Assert.IsFalse(string.IsNullOrEmpty(((RequestsMetricsData)controller.DataToShow).GChartRequestsLine));
        }

        [TestMethod]
        public void ShouldCleanCommittedRequests()
        {
            string mockProjectUri = "AF06A611-12CE-4C06-B3AD-E2754D12D516";
            MockRequestsService requestsService = new MockRequestsService();
            TestableRequestsController controller = new TestableRequestsController(requestsService);

            controller.CleanCommitted(mockProjectUri);

            Assert.IsTrue(requestsService.CleanCommittedCalled);
            Assert.IsTrue(controller.DataRedirectToAction.ToString().Contains("Action = Read"));
            Assert.IsTrue(controller.DataRedirectToAction.ToString().Contains("Mode = Opened"));
        }
    }

    public class TestableRequestsController : RequestsController
    {
        public object DataToShow { get; set; }
        public object ViewToShow { get; set; }
        public object DataRedirectToAction { get; set; }

        public TestableRequestsController(IRequestsService service)
            : base(service, new MockProjectsService(), new MockProfileService())
        {
        }

        public TestableRequestsController(IRequestsService service, IProfileService profile)
            : base(service, new MockProjectsService(), profile)
        {
        }

        [SecurityPermission(SecurityAction.LinkDemand, Unrestricted = true)]
        protected override void RenderView(string viewName, string masterName, object viewData)
        {
            ViewToShow = viewName;
            DataToShow = viewData;
        }
        protected override void RedirectToAction(object values)
        {
            DataRedirectToAction = values;
        }
    }
}
